﻿//	Copyright (c) 2011 Jonathan Loe
//
//	MIT license (http://en.wikipedia.org/wiki/MIT_License)
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights 
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
//	of the Software, and to permit persons to whom the Software is furnished to do so, 
//	subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all 
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
//	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
//	PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
//	FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
//	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ordinaire.Db;

namespace Ordinaire
{
    public class Taxonomy<TId, TEntity> : TreeDataEntity<TId, TEntity>, IName
        where TEntity : IHierarchy<TId>, IName
    {
        #region Variables

        /// <summary>
        /// Taxonomy unit name.
        /// </summary>
        private string name;

        #endregion

        #region Constructor

        /// <summary>
        /// Returns new instance of Taxonomy.
        /// </summary>
        public Taxonomy()
        {
            TreeDataEntity<TId, TEntity> helper = new TreeDataEntity<TId,TEntity>();
            List<TEntity> entities = helper.GetRoots();
            if (entities.Count == 1)
            {
                TEntity entity = entities[0];
                this.Id        = entity.Id;
                this.ParentId  = entity.ParentId;
                this.name      = entity.Name;
            }
            else if (entities.Count > 1)
            {
                ExceptionFactory.Create<OException>(ExceptionMessage.MoreThanOneFound, "roots");
            }
        }

        /// <summary>
        /// Returns a new instance of Ordinaire.Taxonomy with the specified root name.
        /// </summary>
        /// <param name="name">taxonomy name</param>
        public Taxonomy(string name)
        {
            if (String.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }

            try
            {
                var getNode = from n in Context.GetTable(typeof(TEntity)).Cast<TEntity>()
                              where n.Name == name
                              select n;
                TEntity entity = getNode.SingleOrDefault();

                this.Id       = entity.Id;
                this.ParentId = entity.ParentId;
                this.name     = entity.Name;
            }
            catch (Exception ex)
            {
                ExceptionFactory.Create<OException>(ex, ExceptionMessage.MoreThanOneFound, String.Format("items with '{0}'", name));
            }
        }

        #endregion

        #region Property methods

        /// <summary>
        /// Gets or sets the taxonomy name.
        /// </summary>
        public String Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        #endregion

        /// <summary>
        /// Returns new taxonomy with the specified name if the INSERT is successful.
        /// </summary>
        /// <param name="name">taxonomy name</param>
        /// <returns>new taxonomy with the specified taxonomy name</returns>
        public static Taxonomy<TId, TEntity> Create(string name)
        {
            if (String.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }

            try
            {
                TEntity entity = typeof(TEntity).Instance<TEntity>();
                entity.Name = name;

                // Use TreeDataHelper for its DataContext
                TreeDataEntity<TId, TEntity> helper = new TreeDataEntity<TId, TEntity>();
                helper.Context.GetTable(typeof(TEntity)).InsertOnSubmit(entity);
                helper.Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                ExceptionFactory.Create<OException>(ex, ExceptionMessage.Failure, "create new taxonomy");
            }

            return new Taxonomy<TId, TEntity>(name);
        }
    }
}
